package com.zhihuishu.micro.course.openapi.app.impl.teacher;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

import com.able.openapi.zhsCourse.IOnlineSchoolForZhsCourseService;
import com.google.common.collect.Lists;
import com.zhihuishu.micro.course.dao.CourseTeacherMapper;
import com.zhihuishu.micro.course.dto.CourseBaseInfoDto;
import com.zhihuishu.micro.course.dto.CourseClipsDto;
import com.zhihuishu.micro.course.dto.CourseDto;
import com.zhihuishu.micro.course.helper.RedisKeyHelper;
import com.zhihuishu.micro.course.log.LoggerCollectionEnum;
import com.zhihuishu.micro.course.log.LoggerTemplateUtil;
import com.zhihuishu.micro.course.log.MDCLoggerUtil;
import com.zhihuishu.micro.course.model.CourseStatus;
import com.zhihuishu.micro.course.model.MeetCourse;
import com.zhihuishu.micro.course.model.ScoreAssessRule;
import com.zhihuishu.micro.course.model.TblCourse;
import com.zhihuishu.micro.course.openapi.app.dto.ChapterWebDto;
import com.zhihuishu.micro.course.openapi.app.dto.CourseBaseInfoOpenDto;
import com.zhihuishu.micro.course.openapi.app.dto.CourseClipsOpenDto;
import com.zhihuishu.micro.course.openapi.app.dto.CourseOpenDto;
import com.zhihuishu.micro.course.openapi.app.dto.CourseStatusDto;
import com.zhihuishu.micro.course.openapi.app.dto.LessonVideoWebDto;
import com.zhihuishu.micro.course.openapi.app.dto.LessonWebDto;
import com.zhihuishu.micro.course.openapi.app.enmus.CourseModelEnum;
import com.zhihuishu.micro.course.openapi.app.teacher.AppCourseOpenServiceForTeacher;
import com.zhihuishu.micro.course.openapi.online.CourseOpenService;
import com.zhihuishu.micro.course.service.AppCourseInfoService;
import com.zhihuishu.micro.course.service.ChapterService;
import com.zhihuishu.micro.course.service.CourseClipsService;
import com.zhihuishu.micro.course.service.CourseService;
import com.zhihuishu.micro.course.service.FirstStepStatService;
import com.zhihuishu.micro.course.service.LessonService;
import com.zhihuishu.micro.course.service.LessonVideoService;
import com.zhihuishu.micro.course.service.MeetCourseService;
import com.zhihuishu.micro.course.service.ScoreAssessRuleService;
import com.zhihuishu.remote.ErrorCode;
import com.zhihuishu.remote.RemoteException;
import com.zhihuishu.remote.RemoteResult;
import com.zhihuishu.toolkit.helper.BeanHelper;
import com.zhihuishu.toolkit.jedis.BeanWrapper;
import com.zhihuishu.toolkit.jedis.JedisHelper;
import com.zhihuishu.toolkit.jedis.JedisHelper.Handler;
import com.zhihuishu.toolkit.jedis.JedisHelper.ReturnHandler;
import com.zhihuishu.toolkit.jedis.template.JedisExecutor;

@Service("appCourseOpenServiceForTeacher")
public class AppCourseOpenServiceForTeacherImpl implements AppCourseOpenServiceForTeacher {

    @Resource
    private JedisExecutor jedisExecutor;

    @Resource
    private CourseService courseService;

    @Resource
    private CourseClipsService courseClipsService;

    @Resource
    private AppCourseInfoService appCourseInfoService;

    @Resource
    private IOnlineSchoolForZhsCourseService onlineSchoolForZhsCourseService;

    @Resource
    private ScoreAssessRuleService scoreAssessRuleService;

    @Resource
    // XXX 暂时使用Mapper接口
    private CourseTeacherMapper courseTeacherMapper;

    @Resource
    private CourseOpenService courseOpenService;

    @Resource
    private FirstStepStatService firstStepStateService;

    @Resource
    private ChapterService chapterService;

    @Resource
    private LessonService lessonService;

    @Resource
    private LessonVideoService lessonVideoService;

    @Resource
    private MeetCourseService meetCourseService;

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public RemoteResult<Map<String, Integer>> findProgressByCourseId(Long courseId) throws RemoteException {
        RemoteResult<Map<String, Integer>> result = new RemoteResult<Map<String, Integer>>();
        if (courseId == null) {
            result.setSuccess(false);
            result.setExceptionStack(new Exception("参数不合法:课程id为空！"));
            result.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return result;
        }
        try {
            Map<String, Integer> map = null;
            List<Long> courseIds = new ArrayList<Long>();
            courseIds.add(courseId);
            RemoteResult<Map<Long, Map<String, Integer>>> progressResult = courseOpenService
                    .findProgressByCourseIds(courseIds);
            Map<Long, Map<String, Integer>> progressMap = progressResult.getResult();
            if (progressMap != null && progressMap.size() > 0) {
                map = progressMap.get(courseId);
            }
            result.setResult(map);
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            String str = getStackTrace(e);
            MDCLoggerUtil.saveLogger(e.getMessage() + " || " + str, null,
                    LoggerCollectionEnum.courseProgressCollection, courseId);
            throw new RemoteException(e).setMessage("查询进度出错!");
        }
        return result;
    }

    @Override
    public RemoteResult<Void> delProgressByCourseId(Long courseId) throws RemoteException {
        List<Long> courseIds = new ArrayList<Long>();
        courseIds.add(courseId);
        return courseOpenService.delProgressByCourseIds(courseIds);
    }

    /*
     * @Override public RemoteResult<List<Map<String, String>>>
     * queryCourseIdAndNameForAppCreateCourse(List<Long> courseIds) throws RemoteException {
     * RemoteResult<List<Map<String, String>>> result = new RemoteResult<List<Map<String,
     * String>>>(); if (courseIds != null && courseIds.size() > 0) { List<Map<String, String>>
     * courseList = new ArrayList<Map<String, String>>(); for (Long courseId : courseIds) {
     * CourseDto dto = null; if (courseId != null) { dto = courseService.get(courseId); if (dto !=
     * null) { Map<String, String> data = new HashMap<String, String>(); data.put("courseId",
     * courseId + ""); data.put("name", dto.getName()); courseList.add(data); } } }
     * result.setResult(courseList); } return result; }
     */

    @Override
    public RemoteResult<List<Map<String, String>>> queryCourseIdAndNameForAppCreateCourse(
            final List<Long> courseIds) throws RemoteException {
        RemoteResult<List<Map<String, String>>> result = new RemoteResult<List<Map<String, String>>>();
        if (courseIds != null && courseIds.size() > 0) {
            List<Map<String, String>> courseList = new ArrayList<Map<String, String>>();
            // 先批量查缓存
            BeanWrapper<List<Object>> redisResult = jedisExecutor
                    .executeAndReturn(new ReturnHandler<List<Object>>() {
                        @Override
                        public List<Object> handle(Jedis jedis) {
                            Pipeline pip = jedis.pipelined();
                            for (Long courseId : courseIds) {
                                pip.hmget(RedisKeyHelper.courseKey(courseId), "courseId", "name");
                            }
                            return pip.syncAndReturnAll();
                        }
                    });
            // 查询结果封装
            List<Object> redisCourseDtos = redisResult.getValue();
            Map<String, String> data = null;
            for (Object redisCourse : redisCourseDtos) {
                @SuppressWarnings("unchecked")
				List<String> courseInfo = (List<String>) redisCourse;
                if (StringUtils.isNotEmpty(courseInfo.get(0))
                        && StringUtils.isNotEmpty(courseInfo.get(1))) {
                    data = new HashMap<String, String>();
                    data.put("courseId", courseInfo.get(0));
                    data.put("name", courseInfo.get(1));
                    courseList.add(data);
                }
            }
            // 缓存中未查到则查库
            if (courseList.size() != courseIds.size()) {
                getCourseFromDb(courseIds, courseList);
            }
            result.setResult(courseList);
        }
        return result;
    }

    /**
     * 缓存中无数据的课程查询数据库
     * 
     * @author ztl
     * @date 2017年3月31日下午1:16:38
     * @param courseIds
     * @param courseList
     */
    private void getCourseFromDb(final List<Long> courseIds, List<Map<String, String>> courseList) {
        Map<String, String> data;
        List<Long> noRedisCourseIds = new ArrayList<Long>();// 缓存中无数据的课程ID集合
        for (Long courseId : courseIds) {
            boolean flag = false;// true缓存中查询到了数据 false缓存无数据
            for (Map<String, String> course : courseList) {
                if (StringUtils.isNotEmpty(course.get("courseId"))
                        && courseId.equals(Long.parseLong(course.get("courseId")))) {
                    // 缓存中查出了数据
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                noRedisCourseIds.add(courseId);
            }
        }
        // 缓存无数据的课程查询数据库
        List<TblCourse> dbCourseList = courseService.findCourseByCourseIds(noRedisCourseIds);
        for (final TblCourse dbCourse : dbCourseList) {
            if (dbCourse != null) {
                data = new HashMap<String, String>();
                data.put("courseId", dbCourse.getCourseId() + "");
                data.put("name", dbCourse.getName());
                courseList.add(data);
                final Map<String, String> map = BeanHelper.describe(dbCourse);
                if (!CollectionUtils.isEmpty(map)) {
                    jedisExecutor.execute(new Handler() {
                        @Override
                        public void handle(Jedis jedis) {
                            jedis.hmset(RedisKeyHelper.courseKey(dbCourse.getCourseId()), map);
                        }
                    });
                }
            }
        }
    }

    @Override
    public RemoteResult<List<Long>> filterCourseIsNew(List<Long> courseIds) {
        RemoteResult<List<Long>> result = new RemoteResult<List<Long>>();
        if (courseIds == null || courseIds.size() == 0) {
            result.setSuccess(false);
            result.setExceptionStack(new Exception("参数不合法:courseIds为空！"));
            result.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return result;
        }
        List<Map<String, Object>> firstStepStateList = firstStepStateService.countByCourseIds(courseIds);
        if (firstStepStateList != null && firstStepStateList.size() > 0) {
            List<Long> resultList = new ArrayList<Long>();
            for (Map<String, Object> map : firstStepStateList) {
                if (map.get("dataCount") != null && Integer.parseInt(map.get("dataCount").toString()) > 0) {
                    resultList.add(Long.parseLong(map.get("courseId").toString()));
                }
            }
            result.setResult(resultList);
        }
        return result;
    }

    @Override
    public RemoteResult<Void> updateCourseBackground(String content, long courseId, long userId) {
        RemoteResult<Void> remoteResult = new RemoteResult<Void>();
        try {
            Assert.notNull(content, "更新内容不能为空");
            if (logger.isDebugEnabled()) {
                logger.debug("更新课程{},课程背景为{},更新用户为{}", courseId, content, userId);
            }
            courseService.updateCourseBackground(content, courseId, userId);
            LoggerTemplateUtil.saveLogger(String.format("更新课程背景:%s", content), userId,
                    LoggerCollectionEnum.courseCollection, courseId);

        } catch (Exception e) {
            remoteResult.setExceptionStack(e);
            remoteResult.setSuccess(false);
            logger.error("更新课程背景错误,courseId={},背景内容={}", courseId, content, e);

        }
        return remoteResult;
    }

    @Override
    public RemoteResult<Void> updateCourseTarget(String content, long courseId, long userId) {
        RemoteResult<Void> remoteResult = new RemoteResult<Void>();
        try {
            Assert.notNull(content, "更新内容不能为空");
            if (logger.isDebugEnabled()) {
                logger.debug("接受参数:content={},courseId={},userId={}", content, courseId, userId);
            }
            courseService.updateCourseTarget(content, courseId, userId);
            LoggerTemplateUtil.saveLogger(String.format("更新课程目标:%s", content), userId,
                    LoggerCollectionEnum.courseCollection, courseId);
        } catch (Exception e) {
            remoteResult.setExceptionStack(e);
            remoteResult.setSuccess(false);
            logger.error("更新课程目标错误,courseId={},content={}", courseId, content, e);
        }
        return remoteResult;

    }

    @Override
    public RemoteResult<Void> updateCourseDesignPrinciple(String content, long courseId, long userId) {
        RemoteResult<Void> remoteResult = new RemoteResult<Void>();
        try {
            Assert.notNull(content, "更新内容不能为空");
            if (logger.isDebugEnabled()) {
                logger.debug("接受参数:content={},courseId={},userId={}", content, courseId, userId);
            }
            courseService.updateCourseDesignPrinciple(content, courseId, userId);
            LoggerTemplateUtil.saveLogger(String.format("更新课程设原则:%s", content), userId,
                    LoggerCollectionEnum.courseCollection, courseId);
        } catch (Exception e) {
            remoteResult.setExceptionStack(e);
            remoteResult.setSuccess(false);
            logger.error("更新课程设计原则发生错误,courseId={},content={}", courseId, content, e);
        }
        return remoteResult;

    }

    @Override
    public RemoteResult<CourseOpenDto> queryCourseInfo(long courseId) {
        RemoteResult<CourseOpenDto> remoteResult = new RemoteResult<CourseOpenDto>();
        try {

            CourseDto course = courseService.get(courseId);
            if (logger.isDebugEnabled()) {
                logger.debug("查询到的课程信息为{}", course);
            }
            if (course != null) {
                CourseOpenDto basicInfo = BeanHelper.transTo(course, CourseOpenDto.class);
                remoteResult.setResult(basicInfo);
                if (logger.isDebugEnabled()) {
                    logger.debug("转换后的课程信息为:{}", basicInfo);
                }
            }

        } catch (Exception e) {
            remoteResult.setExceptionStack(e);
            remoteResult.setSuccess(false);
            logger.error("查询课程信息发生错误,courseId={}", courseId, e);
        }
        return remoteResult;
    }

    @Override
    public RemoteResult<Void> update(CourseOpenDto course, long updateUser, long courseId)
            throws RemoteException {
        RemoteResult<Void> remoteResult = new RemoteResult<Void>();
        try {
            Assert.notNull(course, "更新对象不能为空");
            Assert.notNull(course.getCourseId(), "主键不能为空");
            Assert.notNull(updateUser, "操作用户不能为空");
            Assert.notNull(courseId, "课程id不能为空");
            CourseDto courseDto = BeanHelper.transTo(course, CourseDto.class);
            if (logger.isDebugEnabled()) {
                logger.debug("要更新的课程信息为:{}", courseDto);
            }
            courseService.update(courseDto, updateUser);

            LoggerTemplateUtil.saveLogger("app更新课程", updateUser, LoggerCollectionEnum.courseCollection,
                    courseId);
        } catch (Exception e) {
            remoteResult.setExceptionStack(e);
            remoteResult.setSuccess(false);
        }
        return remoteResult;

    }

    @Override
    public RemoteResult<Void> updateCourseClips(CourseClipsOpenDto clips, long updateUser, long courseId)
            throws RemoteException {
        RemoteResult<Void> result = new RemoteResult<Void>();
        // 参数检查
        if (clips == null || clips.getClipsId() == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return result;
        }
        try {
            courseClipsService.update(BeanHelper.transTo(clips, CourseClipsDto.class), updateUser);
            MDCLoggerUtil.saveLogger(String.format("app建课第六步：接口添加或更新课程片花%s", clips), updateUser,
                    LoggerCollectionEnum.coursePromotionCollection, courseId);
        } catch (Exception e) {
            throw new RemoteException(e).setMessage("更新课程片花执行出错!");
        }

        return result;
    }

    @Override
    public RemoteResult<Void> updateCourseBaseInfo(CourseBaseInfoOpenDto courseBaseInfoOpenDto,
            long courseId, long userId) {
        RemoteResult<Void> remoteResult = new RemoteResult<Void>();
        try {
            Assert.notNull(courseBaseInfoOpenDto, "更新对象不能为空");
            Assert.notNull(courseBaseInfoOpenDto.getIsBasicInfoComplete(), "课程基本信息完整的不能为空");
            if (logger.isDebugEnabled()) {
                logger.debug("更新课程基本信息的数据为courseBaseInfoOpenDto={}", courseBaseInfoOpenDto);
            }
            courseService.updateBaseInfo(BeanHelper.transTo(courseBaseInfoOpenDto, CourseBaseInfoDto.class),
                    userId, courseId);
            LoggerTemplateUtil.saveLogger(
                    String.format("更新课程基本信息,courseBaseInfoOpenDto=%s", courseBaseInfoOpenDto), userId,
                    LoggerCollectionEnum.courseCollection, courseId);
            courseBaseInfoOpenDto.setCourseId(courseId);

        } catch (Exception e) {
            remoteResult.setExceptionStack(e);
            remoteResult.setSuccess(false);
            logger.error("更新课程基本信息出错,传入的参数为{}", courseBaseInfoOpenDto, e);

        }
        return remoteResult;

    }

    @Override
    public RemoteResult<Void> updateCourseModel(CourseModelEnum courseModelEnum, long courseId, long userId) {
        RemoteResult<Void> remoteResult = new RemoteResult<Void>();
        try {
            if (logger.isDebugEnabled()) {
                logger.debug("更新课程模式,courseId={},userId={},model={}", courseId, userId,
                        courseModelEnum.getCode());
            }
            courseService.updateCourseModel(courseModelEnum.getCode(), courseId, userId);
        } catch (Exception e) {
            remoteResult.setExceptionStack(e);
            remoteResult.setSuccess(false);
        }
        return remoteResult;

    }

    @Override
    public RemoteResult<CourseClipsOpenDto> queryCourseClips(long clipsId) throws RemoteException {
        RemoteResult<CourseClipsOpenDto> result = new RemoteResult<CourseClipsOpenDto>();
        try {
            CourseClipsDto clips = courseClipsService.get(clipsId);
            result.setResult(BeanHelper.transTo(clips, CourseClipsOpenDto.class));
        } catch (Exception e) {
            throw new RemoteException(e).setMessage("查询课程片花出错!");
        }

        return result;
    }

    @Override
    public RemoteResult<List<ChapterWebDto>> queryCourseAllInfo(final long courseId) {

        RemoteResult<List<ChapterWebDto>> result = new RemoteResult<List<ChapterWebDto>>();
        // XXX
        // 参考com.zhihuishu.micro.course.openapi.online.impl.ChapterLessonOpenServiceImpl#queryChapterBasicInfos逻辑
        final List<ChapterWebDto> chapters = new ArrayList<ChapterWebDto>();
        jedisExecutor.execute(new Handler() {
            @Override
            public void handle(Jedis jedis) {
                // 根据课程ID，获取章列表
                Set<String> chapterIds = jedis.smembers(JedisHelper
                        .key("cc:course", courseId, "chapters:all"));
                if (CollectionUtils.isEmpty(chapterIds)) {
                    chapterIds = chapterService.queryChapterIdsByCourseIdAndAddToCache(courseId);
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("查询到所有的章的集合为:{}", chapterIds);
                }

                // 根据课程ID，获取节列表
                Set<String> lessonIds = jedis.smembers(JedisHelper.key("cc:course", courseId, "lessons"));
                if (CollectionUtils.isEmpty(lessonIds)) {
                    lessonIds = lessonService.queryLessonIdsByCourseId(courseId);
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("查询到所有的节的数据为:{}", lessonIds);
                }

                // 根据课程ID，获取小节列表
                Set<String> lvIds = jedis.smembers(JedisHelper.key("cc:course", courseId, "lvs"));
                if (CollectionUtils.isEmpty(lvIds)) {
                    lvIds = lessonVideoService.queryLessonVideoIdsByCourseId(courseId);
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("查询到所有的小节的数据为:{}", lvIds);
                }
                // 使用管道获取数据
                Pipeline pip = jedis.pipelined();
                // 获取章数据
                if (!CollectionUtils.isEmpty(chapterIds))
                    for (String chapterId : chapterIds) {
                        if (chapterId == null)
                            continue;
                        pip.hmget(JedisHelper.key("cc:chapter", chapterId), "name", "rank", "limitDay",
                                "isPass", "id", "studyHour", "description");
                    }
                // 获取节数据
                if (!CollectionUtils.isEmpty(lessonIds))
                    for (String lessonId : lessonIds) {
                        if (lessonId == null)
                            continue;
                        pip.hmget(JedisHelper.key("cc:lesson", lessonId), "chapterId", "name", "rank",
                                "videoId", "videoSec", "haveChildren", "knowledgeCardTotal",
                                "courseDataTotal", "id", "introduction", "speaker");
                    }
                // 获取小节数据
                if (!CollectionUtils.isEmpty(lvIds))
                    for (String lvId : lvIds) {
                        pip.hmget(JedisHelper.key("cc:lv", lvId), "lessonId", "name", "rank", "videoId",
                                "videoSec", "id", "speaker");
                    }
                // 提取结果
                List<Object> result = pip.syncAndReturnAll();
                if (CollectionUtils.isEmpty(result))
                    return;
                List<LessonWebDto> lessons = new ArrayList<LessonWebDto>();
                List<LessonVideoWebDto> lvs = new ArrayList<LessonVideoWebDto>();
                for (int i = 0, len = result.size(); i < len; i++) {
                    Object obj = result.get(i);
                    if (i < chapterIds.size()) {
                        ChapterWebDto chapter = toChapter(obj);
                        if (chapter != null && chapter.getId() != null)
                            chapters.add(chapter);
                    } else if (i < chapterIds.size() + lessonIds.size()) {
                        LessonWebDto lesson = toLesson(obj);
                        if (lesson != null && lesson.getId() != null && lesson.getChapterId() != null)
                            lessons.add(lesson);
                    } else {
                        LessonVideoWebDto lv = toLessonVideo(obj);
                        if (lv != null && lv.getId() != null && lv.getLessonId() != null
                                && lv.getRank() != null)
                            lvs.add(lv);
                    }
                }
                if (CollectionUtils.isEmpty(chapters))
                    return;

                // 组合数据
                // 如果小节列表不为空，将小节写入到节中
                if (!CollectionUtils.isEmpty(lvs)) {
                    // 小节列表排序
                    Collections.sort(lvs, new Comparator<LessonVideoWebDto>() {
                        @Override
                        public int compare(LessonVideoWebDto o1, LessonVideoWebDto o2) {
                            if (o1 == null || o2 == null)
                                return 0;
                            return o1.getRank().compareTo(o2.getRank());
                        }
                    });
                    // 组合数据
                    for (LessonWebDto lesson : lessons) {
                        for (LessonVideoWebDto lv : lvs) {
                            if (lv.getLessonId().equals(lesson.getId())) {
                                if (lesson.getLessonVideos() == null) {
                                    lesson.setLessonVideos(new ArrayList<LessonVideoWebDto>());
                                }
                                lesson.getLessonVideos().add(lv);
                            }
                        }
                    }
                }
                // 如果节列表不为空，将节写入到章中
                if (!CollectionUtils.isEmpty(lessons)) {
                    // 小节列表排序
                    Collections.sort(lessons, new Comparator<LessonWebDto>() {
                        @Override
                        public int compare(LessonWebDto o1, LessonWebDto o2) {
                            if (o1 == null || o2 == null)
                                return 0;
                            return o1.getRank().compareTo(o2.getRank());
                        }
                    });
                    // 组合数据
                    for (ChapterWebDto cwd : chapters) {
                        for (LessonWebDto lesson : lessons) {
                            if (lesson == null || lesson.getId() == null)
                                continue;
                            if (cwd.getId().equals(lesson.getChapterId())) {
                                if (cwd.getLessons() == null)
                                    cwd.setLessons(new ArrayList<LessonWebDto>());
                                cwd.getLessons().add(lesson);
                            }
                        }
                    }
                }
            }
        });
        if (!CollectionUtils.isEmpty(chapters)) {

            Collections.sort(chapters, new Comparator<ChapterWebDto>() {

                @Override
                public int compare(ChapterWebDto o1, ChapterWebDto o2) {
                    if (o1 == null || o2 == null) {
                        return 0;
                    }
                    return o1.getRank().compareTo(o2.getRank());
                }

            });
            if (logger.isDebugEnabled()) {
                logger.debug("章节结构的列表为:{}", chapters);
            }
            result.setResult(chapters);
        }

        return result;

    }

    /**
     * 从Redis获取的数据转换为章对象：[古代上海人事物, 1, 10, 1, 1121] "name", "rank", "limitDay","isPass",
     * "id","studyHour","description");
     * 
     * @param obj
     * @return
     */
    private ChapterWebDto toChapter(Object obj) {
        if (obj == null)
            return null;
        @SuppressWarnings("unchecked")
        List<String> list = (List<String>) obj;

        ChapterWebDto cwd = new ChapterWebDto();
        if (list.get(0) != null)// 名称
            cwd.setName(list.get(0).toString());
        if (list.get(1) != null)// 排序
            cwd.setRank(NumberUtils.toInt(list.get(1).toString()));
        if (list.get(2) != null)// 计划天数
            cwd.setLimitDay(NumberUtils.toInt(list.get(2).toString()));
        if (list.get(4) != null)// id
            cwd.setId(NumberUtils.toInt(list.get(4).toString()));
        if (list.get(5) != null) {// 学时
            cwd.setStudyHour(NumberUtils.toInt(list.get(5).toString()));
        }
        if (list.get(6) != null) {// 描述
            cwd.setIntroduction(list.get(6));
        }
        return cwd;
    }

    /**
     * pip.hmget(JedisHelper.key("cc:lesson", lessonId), "chapterId", "name", "rank", "videoId",
     * "videoSec", "haveChildren", "knowledgeCardTotal", "courseDataTotal", "id","introduction");
     * 
     * @param obj
     * @return
     */
    private LessonWebDto toLesson(Object obj) {
        if (obj == null)
            return null;
        @SuppressWarnings("unchecked")
        List<String> list = (List<String>) obj;
        LessonWebDto lwd = new LessonWebDto();
        if (list.get(0) != null)// 章id
            lwd.setChapterId(NumberUtils.toInt(list.get(0).toString()));
        if (list.get(1) != null)// 节名称
            lwd.setName(list.get(1).toString());
        if (list.get(2) != null)// 排序
            lwd.setRank(NumberUtils.toInt(list.get(2).toString()));
        if (list.get(3) != null && !list.get(3).equals("0")) {// 视频id不为空且视频id不为0(缓存中视频id不存在为0)
            lwd.setVideoId(NumberUtils.toLong(list.get(3).toString()));
        } else {
            lwd.setVideoId(0L);// 与缓存中保持一致
        }

        if (list.get(4) != null) {// 视频时常
            lwd.setVideoSec(NumberUtils.toInt(list.get(4).toString()));
        } else {
            lwd.setVideoSec(0);// 与缓存中保持一致
        }

        if (list.get(5) != null)// 是否有子小节
            lwd.setHaveChildren(NumberUtils.toInt(list.get(5).toString()) > 0);
        /*
         * if (list.get(6) != null)
         * lwd.setKnowledgeCardTotal(NumberUtils.toInt(list.get(6).toString())); if (list.get(7) !=
         * null) lwd.setCourseDataTotal(NumberUtils.toInt(list.get(7).toString()));
         */
        if (list.get(8) != null)// 节id
            lwd.setId(NumberUtils.toInt(list.get(8).toString()));
        if (list.get(9) != null) {// 主讲人
            lwd.setSpeaker(list.get(9).toString());

        }
        return lwd;
    }

    private LessonVideoWebDto toLessonVideo(Object obj) {
        if (obj == null)
            return null;
        @SuppressWarnings("unchecked")
        List<String> list = (List<String>) obj;
        LessonVideoWebDto lvw = new LessonVideoWebDto();
        if (list.get(0) != null)// 节id
            lvw.setLessonId(NumberUtils.toInt(list.get(0).toString()));// 节id
        if (list.get(1) != null)// 名称
            lvw.setName(list.get(1).toString());
        if (list.get(2) != null)// 顺序
            lvw.setRank(NumberUtils.toInt(list.get(2).toString()));
        if (list.get(3) != null && !list.get(3).equals("0")) {// 视频id存在且不为0(缓存中视频id不存在的时候设置为0)
            lvw.setVideoId(NumberUtils.toLong(list.get(3).toString()));
        } else {
            lvw.setVideoId(0L);// 与缓存中保持一致
        }
        if (list.get(4) != null) {// 视频上传
            lvw.setVideoSec(NumberUtils.toInt(list.get(4).toString()));
        } else {
            lvw.setVideoSec(0);// 与缓存中保持一致
        }
        if (list.get(5) != null)// 小节id
            lvw.setId(NumberUtils.toInt(list.get(5).toString()));
        if (list.get(6) != null) {// 主讲人
            lvw.setSpeaker(list.get(6).toString());

        }
        return lvw;
    }

    @Override
    public RemoteResult<CourseStatusDto> findCoursesStatus(long courseId) {

        RemoteResult<CourseStatusDto> remoteResult = new RemoteResult<CourseStatusDto>();
        CourseStatusDto courseStatusDto = null;
        try {
            Assert.notNull(courseId > 0, "参数不合法");
            List<Long> courseIds = Lists.newArrayListWithCapacity(1);
            courseIds.add(courseId);
            List<CourseStatus> courseStatus = courseService.findCoursesStatus(courseIds);
            if (logger.isDebugEnabled()) {
                logger.debug("查询到的结果信息为{}", courseStatus);
            }
            if (courseStatus != null && courseStatus.size() > 0) {

                courseStatusDto = new CourseStatusDto();
                BeanUtils.copyProperties(courseStatus.get(0), courseStatusDto);

                remoteResult.setResult(courseStatusDto);
            }
        } catch (Exception e) {
            remoteResult.setSuccess(false);
            remoteResult.setExceptionStack(e);
        }
        return remoteResult;

    }

    @Override
    public RemoteResult<Boolean> findScoreAssessRuleComplete(long courseId, int courseMode)
            throws RemoteException {
        RemoteResult<Boolean> remoteResult = new RemoteResult<Boolean>();
        if (courseId == 0) {
            remoteResult.setSuccess(false);
            remoteResult.setExceptionStack(new Exception("参数不合法:courseId为0！"));
            remoteResult.setErrorCode(ErrorCode.ARGUMENTS_ILLEGALITY);
            return remoteResult;
        }
        try {
            CourseDto courseDto = courseService.get(courseId);
            courseMode = courseDto.getCourseMode() != null ? courseDto.getCourseMode() : 1; // 课程类型改走库查询
                                                                                            // 查出为空时，默认为混合式课程
            ScoreAssessRule scoreAssessRule = scoreAssessRuleService.findByCourseId(courseId);
            if (scoreAssessRule == null) {
                remoteResult.setResult(false);
                return remoteResult;
            }
            Double onlineScoreShare = ifNull(scoreAssessRule.getOnlineScoreShare()); // 线上成绩占比
            Double meetCourseScoreShare = ifNull(scoreAssessRule.getMeetCourseScoreShare()); // 见面课成绩占比
            Double finalExamScoreShare = ifNull(scoreAssessRule.getFinalExamScoreShare()); // 期末考试成绩占比
            Double bbsScore = ifNull(scoreAssessRule.getBbsScore()); // 论坛得分
            if (courseMode == 2) {
                // 如果是纯在线课程，则没有见面课
                meetCourseScoreShare = 0.0;
            }
            boolean flag = true;
            // 论坛作为附加分
            if (scoreAssessRule.getIsAddScore() != null && scoreAssessRule.getIsAddScore().equals(1)) {
                if (add(onlineScoreShare, meetCourseScoreShare, finalExamScoreShare, 0, 0) != 100) {
                    flag = false;
                }
            } else {
                // 论坛不作为附加分，即100分内
                if (add(onlineScoreShare, meetCourseScoreShare, finalExamScoreShare, bbsScore, 0) != 100) {
                    flag = false;
                }
            }
            //
            List<MeetCourse> meetCourses = meetCourseService.getMeetCourseList(courseId);
            // 判断见面课各项分相加是否等于见面课设置分、考勤分和现场得分是否为空
            if (courseMode == 1) {
                Double checkAddSiteScore = 0.0;
                if (!CollectionUtils.isEmpty(meetCourses)) {
                    for (MeetCourse meetCourse : meetCourses) {
                        if (meetCourse.getIsAddScore() == null || meetCourse.getIsAddScore().equals(0)) {
                            continue;
                        }
                        if (meetCourse.getCheckScore() == null || meetCourse.getSiteScore() == null) {
                            flag = false;
                            break;
                        }
                        checkAddSiteScore += add(meetCourse.getCheckScore(), meetCourse.getSiteScore());
                    }
                }
                if (!checkAddSiteScore.equals(meetCourseScoreShare)) {
                    flag = false;
                }
            }
            remoteResult.setResult(flag);
        } catch (Exception e) {
            e.printStackTrace();
            remoteResult.setExceptionStack(e);
            remoteResult.setSuccess(false);
            logger.error("查询考核标准完整度异常,courseId={}", courseId, e);
        }
        return remoteResult;
    }

    private double add(double num1, double num2, double num3, double num4, double num5) {
        BigDecimal bd1 = new BigDecimal(Double.toString(num1));
        BigDecimal bd2 = new BigDecimal(Double.toString(num2));
        BigDecimal bd3 = new BigDecimal(Double.toString(num3));
        BigDecimal bd4 = new BigDecimal(Double.toString(num4));
        BigDecimal bd5 = new BigDecimal(Double.toString(num5));
        return bd1.add(bd2).add(bd3).add(bd4).add(bd5).doubleValue();
    }

    private double add(double num1, double num2) {
        BigDecimal bd1 = new BigDecimal(Double.toString(num1));
        BigDecimal bd2 = new BigDecimal(Double.toString(num2));
        return bd1.add(bd2).doubleValue();
    }

    private Double ifNull(Double score) {
        if (score == null) {
            return 0.0;
        }
        return score;
    }

    /**
     * 获取异常堆栈信息
     * 
     * @param t
     * @return
     */
    private String getStackTrace(Throwable t) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            t.printStackTrace(pw);
            return sw.toString();
        } finally {
            pw.close();
        }
    }

}
